#pragma once
#ifndef MYDIRECTDRAW_H
#define MYDIRECTDRAW_H

#include "common.h"
#include "MyDirect3D7.h"

class MyDirectDraw : public IDirectDraw7  {
public:
    MyDirectDraw(IDirectDraw7* directDraw7) : directDraw7(directDraw7) {
        DebugWrite("MyDirectDraw::MyDirectDraw\n");
    }

    /*** IUnknown methods ***/
    HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObj) {
        DebugWrite("MyDirectDraw::QueryInterface\n");
        HRESULT hr = this->directDraw7->QueryInterface(riid, ppvObj);
        if (SUCCEEDED(hr) && riid == IID_IDirect3D7) {
            *ppvObj = new MyDirect3D7((IDirect3D7*)*ppvObj);
        }

        return hr;
    }

    ULONG STDMETHODCALLTYPE AddRef() {
        DebugWrite("MyDirectDraw::AddRef\n");
        return this->directDraw7->AddRef();
    }

    ULONG STDMETHODCALLTYPE Release() {
        DebugWrite("MyDirectDraw::Release\n");
        ULONG count = this->directDraw7->Release();
        if (count == 0) {
            delete this;
        }

        return count;
    }

    /*** IDirectDraw7 methods ***/
    HRESULT STDMETHODCALLTYPE GetAvailableVidMem(LPDDSCAPS2 lpDDSCaps2, LPDWORD lpdwTotal, LPDWORD lpdwFree) {
        DebugWrite("MyDirectDraw::GetAvailableVidMem\n");
        return this->directDraw7->GetAvailableVidMem(lpDDSCaps2, lpdwTotal, lpdwFree);
    }

    HRESULT STDMETHODCALLTYPE GetCaps(LPDDCAPS lpDDDriverCaps, LPDDCAPS lpDDHELCaps) {
        DebugWrite("MyDirectDraw::GetCaps\n");
        return this->directDraw7->GetCaps(lpDDDriverCaps, lpDDHELCaps);
    }

    HRESULT STDMETHODCALLTYPE SetCooperativeLevel(HWND hWnd, DWORD dwFlags) {
        DebugWrite("MyDirectDraw::SetCooperativeLevel\n");
        return this->directDraw7->SetCooperativeLevel(hWnd, dwFlags);
    }

    HRESULT STDMETHODCALLTYPE GetDeviceIdentifier(LPDDDEVICEIDENTIFIER2 lpdddi, DWORD dwFlags) {
        DebugWrite("MyDirectDraw::GetDeviceIdentifier\n");
        return this->directDraw7->GetDeviceIdentifier(lpdddi, dwFlags);
    }

    HRESULT STDMETHODCALLTYPE GetDisplayMode(LPDDSURFACEDESC2 lpDDSurfaceDesc2) {
        DebugWrite("MyDirectDraw::GetDisplayMode\n");
        return this->directDraw7->GetDisplayMode(lpDDSurfaceDesc2);
    }

    HRESULT STDMETHODCALLTYPE SetDisplayMode(DWORD dwWidth, DWORD dwHeight, DWORD dwBPP, DWORD dwRefreshRate, DWORD dwFlags) {
        DebugWrite("MyDirectDraw::SetDisplayMode\n");
        return this->directDraw7->SetDisplayMode(dwWidth, dwHeight, dwBPP, dwRefreshRate, dwFlags);
    }

    HRESULT STDMETHODCALLTYPE GetFourCCCodes(LPDWORD lpNumCodes, LPDWORD lpCodes) {
        DebugWrite("MyDirectDraw::GetFourCCCodes\n");
        return this->directDraw7->GetFourCCCodes(lpNumCodes, lpCodes);
    }

    HRESULT STDMETHODCALLTYPE GetGDISurface(LPDIRECTDRAWSURFACE7 FAR *lplpGDIDDSSurface) {
        DebugWrite("MyDirectDraw::GetGDISurface\n");
        return this->directDraw7->GetGDISurface(lplpGDIDDSSurface);
    }

    HRESULT STDMETHODCALLTYPE GetMonitorFrequency(LPDWORD lpdwFrequency) {
        DebugWrite("MyDirectDraw::GetMonitorFrequency\n");
        return this->directDraw7->GetMonitorFrequency(lpdwFrequency);
    }

    HRESULT STDMETHODCALLTYPE GetScanLine(LPDWORD lpdwScanLine) {
        DebugWrite("MyDirectDraw::GetScanLine\n");
        return this->directDraw7->GetScanLine(lpdwScanLine);
    }

    HRESULT STDMETHODCALLTYPE GetSurfaceFromDC(HDC hdc,	LPDIRECTDRAWSURFACE7 * lpDDS) {
        DebugWrite("MyDirectDraw::GetSurfaceFromDC\n");
        return this->directDraw7->GetSurfaceFromDC(hdc, lpDDS);
    }

    HRESULT STDMETHODCALLTYPE GetVerticalBlankStatus(LPBOOL lpbIsInVB) {
        DebugWrite("MyDirectDraw::GetVerticalBlankStatus\n");
        return this->directDraw7->GetVerticalBlankStatus(lpbIsInVB);
    }

    HRESULT STDMETHODCALLTYPE Compact() {
        DebugWrite("MyDirectDraw::Compact\n");
        return this->directDraw7->Compact();
    }

    HRESULT STDMETHODCALLTYPE CreateClipper(DWORD dwFlags, LPDIRECTDRAWCLIPPER FAR *lplpDDClipper, IUnknown FAR *pUnkOuter) {
        DebugWrite("MyDirectDraw::CreateClipper\n");
        return this->directDraw7->CreateClipper(dwFlags, lplpDDClipper, pUnkOuter);
    }

    HRESULT STDMETHODCALLTYPE CreatePalette(DWORD dwFlags, LPPALETTEENTRY lpDDColorArray, LPDIRECTDRAWPALETTE FAR *lplpDDPalette, IUnknown FAR *pUnkOuter) {
        DebugWrite("MyDirectDraw::CreatePalette\n");
        return this->directDraw7->CreatePalette(dwFlags, lpDDColorArray, lplpDDPalette, pUnkOuter);
    }

    HRESULT STDMETHODCALLTYPE CreateSurface(LPDDSURFACEDESC2 lpDDSurfaceDesc2, LPDIRECTDRAWSURFACE7 FAR *lplpDDSurface,  IUnknown FAR *pUnkOuter) {
        DebugWrite("MyDirectDraw::CreateSurface\n");
        return this->directDraw7->CreateSurface(lpDDSurfaceDesc2, lplpDDSurface, pUnkOuter);
    }

    HRESULT STDMETHODCALLTYPE DuplicateSurface(LPDIRECTDRAWSURFACE7 lpDDSurface, LPDIRECTDRAWSURFACE7 FAR *lplpDupDDSurface) {
        DebugWrite("MyDirectDraw::DuplicateSurface\n");
        return this->directDraw7->DuplicateSurface(lpDDSurface, lplpDupDDSurface);
    }

    HRESULT STDMETHODCALLTYPE EnumDisplayModes(DWORD dwFlags, LPDDSURFACEDESC2 lpDDSurfaceDesc2, LPVOID lpContext, LPDDENUMMODESCALLBACK2 lpEnumModesCallback) {
        DebugWrite("MyDirectDraw::EnumDisplayModes\n");
        return this->directDraw7->EnumDisplayModes(dwFlags, lpDDSurfaceDesc2, lpContext, lpEnumModesCallback);
    }

    HRESULT STDMETHODCALLTYPE EnumSurfaces(DWORD dwFlags, LPDDSURFACEDESC2 lpDDSD2, LPVOID lpContext, LPDDENUMSURFACESCALLBACK7 lpEnumSurfacesCallback) {
        DebugWrite("MyDirectDraw::EnumSurfaces\n");
        return this->directDraw7->EnumSurfaces(dwFlags, lpDDSD2, lpContext, lpEnumSurfacesCallback);
    }

    HRESULT STDMETHODCALLTYPE EvaluateMode(DWORD dwFlags, DWORD  *pSecondsUntilTimeout) {
        DebugWrite("MyDirectDraw::EvaluateMode\n");
        return this->directDraw7->EvaluateMode(dwFlags, pSecondsUntilTimeout);
    }

    HRESULT STDMETHODCALLTYPE FlipToGDISurface() {
        DebugWrite("MyDirectDraw::FlipToGDISurface\n");
        return this->directDraw7->FlipToGDISurface();
    }

    HRESULT STDMETHODCALLTYPE Initialize(GUID FAR *lpGUID) {
        DebugWrite("MyDirectDraw::Initialize\n");
        return this->directDraw7->Initialize(lpGUID);
    }

    HRESULT STDMETHODCALLTYPE RestoreDisplayMode() {
        DebugWrite("MyDirectDraw::RestoreDisplayMode\n");
        return this->directDraw7->RestoreDisplayMode();
    }

    HRESULT STDMETHODCALLTYPE WaitForVerticalBlank(DWORD dwFlags, HANDLE hEvent) {
        DebugWrite("MyDirectDraw::WaitForVerticalBlank\n");
        return this->directDraw7->WaitForVerticalBlank(dwFlags, hEvent);
    }

    HRESULT STDMETHODCALLTYPE RestoreAllSurfaces() {
        DebugWrite("MyDirectDraw::RestoreAllSurfaces\n");
        return this->directDraw7->RestoreAllSurfaces();
    }

    HRESULT STDMETHODCALLTYPE StartModeTest(LPSIZE lpModesToTest, DWORD dwNumEntries, DWORD dwFlags) {
        DebugWrite("MyDirectDraw::StartModeTest\n");
        return this->directDraw7->StartModeTest(lpModesToTest, dwNumEntries, dwFlags);
    }

    HRESULT STDMETHODCALLTYPE TestCooperativeLevel() {
        DebugWrite("MyDirectDraw::TestCooperativeLevel\n");
        return this->directDraw7->TestCooperativeLevel();
    }

private:
    IDirectDraw7* directDraw7;
};

#endif
